package com.example.myapplication.livedata.fragment;

import android.os.Bundle;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.arch.core.internal.FastSafeIterableMap;
import androidx.fragment.app.Fragment;
import androidx.lifecycle.MutableLiveData;
import androidx.lifecycle.Observer;

import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;

import com.example.myapplication.bean.ProductInfo;
import com.example.myapplication.databinding.FragmentLiveDataMutableLiveDataBinding;
import com.example.myapplication.livedata.model.LiveDataViewModel;

import java.lang.ref.ReferenceQueue;
import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.WeakHashMap;

/**
 * 1:需要了解WeakReference的概念。
 * 2:需要了解WeakReference和ReferenceQueue的关系。
 * 3:需要了解WeakHashMap的回收原理。
 * 4:需要了解SafeIterableMap数据结构。
 */
public class LiveDataMutableLiveDataFragment extends Fragment {

    private static final String TAG = "LiveDataMutableLiveDataFragment";

    private FragmentLiveDataMutableLiveDataBinding binding;
    private LiveDataViewModel liveDataViewModel = new LiveDataViewModel();
    private WeakHashMap weakHashMap = new WeakHashMap();
    private WeakReference<LiveDataMutableLiveDataFragment> strWeakRef;
    private WeakReference<LiveDataMutableLiveDataFragment> strWeakRef1;
    private ReferenceQueue<Object> queue = new ReferenceQueue<>();
    private int phoneVersion = 1;
    private int eventVersion = 0;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        binding = FragmentLiveDataMutableLiveDataBinding.inflate(getLayoutInflater());
        binding.setLifecycleOwner(this);
        FastSafeIterableMap  map;
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        return binding.getRoot();
    }

    @Override
    public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);
        initData();
        initEvent();
    }


    private void initData() {
        ProductInfo productInfo = new ProductInfo();
        productInfo.setName("苹果手机1代");
        productInfo.setDes("打电话，发短信");
        productInfo.setPrice(5600);

        liveDataViewModel.setProduct(productInfo);

        binding.setModel(liveDataViewModel);

        initWeakData();
    }

    private void initWeakData() {
        for (int i = 0; i < 1000; i++) {
            weakHashMap.put(String.valueOf(i), new LiveDataMutableLiveDataFragment());
        }

        strWeakRef = new WeakReference<>(new LiveDataMutableLiveDataFragment(), queue);
        strWeakRef1 = new WeakReference<>(new LiveDataMutableLiveDataFragment(), queue);
    }

    private void initEvent() {
        binding.btnUpdateProductName.setOnClickListener(v -> {
            phoneVersion++;
            ProductInfo productInfo = liveDataViewModel.getMutableLiveData().getValue();
            productInfo.setName("苹果手机" + phoneVersion + "代");
            liveDataViewModel.getMutableLiveData().setValue(productInfo);
        });

        binding.btnObserverProductName.setOnClickListener(v -> registerObserver());

        binding.btnObserverSetProduct.setOnClickListener(v -> {
            ProductInfo productInfo = new ProductInfo();
            productInfo.setName("new苹果手机1代");
            productInfo.setDes("new 打电话，发短信");
            productInfo.setPrice(5600);
            MutableLiveData<ProductInfo> m = new MutableLiveData<>();
            m.setValue(productInfo);
            liveDataViewModel.setProduct(m);
        });

        binding.btnPrintHashmap.setOnClickListener(v -> {
            printHashMap();
        });

        binding.btnPrintWeak.setOnClickListener(v -> {
            printWeakRef();
        });
    }

    /**
     * gc前：weakHashMap size 大小为填充的数据大小。10000
     * gc后：weakHashMap size 大小为回收后的数据大小，实际上应该是比原始大小小很多。100
     */
    private void printHashMap() {
        Log.e(TAG, "weakHashMap size=" + weakHashMap.size());
    }

    /**
     * gc前：weakRef.get() 持有的对象不为空，且回收队列里不存在任何weakRef对象。
     * gc后：weakRef.get() 持有的对象全为空，且回收对象里存在被回收的weakRef对象。
     */
    private void printWeakRef() {
        if (strWeakRef.get() != null) {
            Log.e(TAG, "弱引用还在" + strWeakRef.get() + "   " + strWeakRef.isEnqueued());
        } else {
            //isEnqueued方法查询引用是不是在回收队列中，在被gc回收后，weakRef会被加入回收队列中。此时未进行回收队列的poll操作时，查询到的是ture。
            Log.e(TAG, "弱引用被回收了:" + strWeakRef.isEnqueued());
        }

        //打印出weakRef的地址信息,跟回收队列里的对象进行对比。
        Log.e(TAG, "弱引用strWeakRef:" + strWeakRef);
        Log.e(TAG, "弱引用strWeakRef1:" + strWeakRef1);

        //循环从收回队列取出被回收的weakRef对象，当weakRef被回收时，会被加入队列中。当调用poll后，会从队列链表中移除。
        for (Object obj;(obj = queue.poll()) != null;) {
            Log.e(TAG, "弱引用队列中的信息" + obj);
        }
    }

    /*****************************************************************************************************************************
     ***************************************************                 *********************************************************
     *****************************************************************************************************************************
     */
    private void registerObserver() {
        liveDataViewModel.getMutableLiveData().observe(getViewLifecycleOwner(), new Observer<ProductInfo>() {
            @Override
            public void onChanged(ProductInfo productInfo) {
                Observer observer = this;
                eventVersion++;
                binding.tvObserverProductName.setText("商品名称：" + productInfo.getName() + "    " + eventVersion);
            }
        });
    }

    private void log(Object obj) {
        Log.e(TAG, obj.toString());
    }
}
